package me.wz.util.sdbc.intercept;

import me.wz.util.Assert;
import me.wz.util.sdbc.IIntercept;

public class RetableIntcpt implements IIntercept {

    private String source[];
    private String target[];

    public static RetableIntcpt re(String ...args) {
        Assert.isTrue(args != null && args.length > 1 && args.length%2 == 0, "table names must be even and more than 1");
        RetableIntcpt ret = new RetableIntcpt();
        ret.source = new String[args.length/2];
        ret.target = new String[args.length/2];
        for(int i=0; i<args.length; i+=2) {
            ret.source[i/2] = args[i];
            ret.target[i/2] = args[i+1];
        }
        return ret;
    }

    @Override
    public String onPrepareStatement(String sql) {
        String ret = sql;
        for(int i=0; i<source.length; i++) {
            ret = retable(ret, source[i], target[i]);
        }
        return ret;
    }

    /**
     * 替换SQL中的表名
     * 1.把转义字符替换为^*
     * 2.把'xxx'替换为'^^^'
     * 3.文本替换
     */
    public static String retable(String sql, String source, String target) {
        Assert.hasText(sql, "sql can't be null");
        Assert.hasText(source, "source can't be null");
        Assert.hasText(target, "target can't be null");
        String str = sql.replaceAll("\\\\.", "^*");
        StringBuilder sd = new StringBuilder();
        for(int i=0, f = 0; i<str.length(); i++) {
            String s = str.substring(i, i+1);
            String r = f == 0 ? s : "^";
            if( "'".equals(s) ) {
                f = f == 1 ? 0 : 1;
                r = s;
            }
            sd.append(r);
        }

        StringBuilder sb = new StringBuilder(sql);
        for(int i=0; i<sd.length();) {
            int idx = sd.indexOf(source, i);
            if( idx == -1 ) {
                break;
            }
            String p = idx > 0 ? sd.substring(idx - 1, idx) : " ";
            String n = idx + source.length() < sd.length() ? sd.substring(idx + source.length(), idx + source.length() + 1) : " ";
            if( isTable(p, n) ) {
                sd.delete(idx, idx + source.length());
                sd.insert(idx, target);
                sb.delete(idx, idx + source.length());
                sb.insert(idx, target);
                i = idx + target.length();
            }
            else {
                i = idx + source.length();
            }
        }
        return sb.toString();
    }
    private static boolean isTable(String prev, String next) {
        return (" ".equals(prev)  || "\r".equals(prev) || "\n".equals(prev) || ".".equals(prev) || "(".equals(prev) || "`".equals(prev))
                && (" ".equals(next)  || "\r".equals(next) || "\n".equals(next) || ".".equals(next) || "(".equals(next) || ")".equals(next) || "`".equals(next))
        ;
    }
}
